package com.fast.log.service;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fast.common.annotation.Log;
import com.fast.common.aop.SysLogAspect;
import com.fast.common.aop.SysLogHandler;
import com.fast.common.constants.AppConst;
import com.fast.common.constants.MQConst;
import com.fast.common.exception.AppException;
import com.fast.common.mq.QueueSender;
import com.fast.common.spring.SpringContextHolder;
import com.fast.common.utils.IpHelper;
import com.fast.common.utils.WebUtil;
import com.fast.common.utils.date.DateUtils;
import com.fast.log.entity.SysLog;
import com.fast.log.mapper.SysLogMapper;

@Service
public class SysLogHandlerImpl implements SysLogHandler {

	private Logger logger = LoggerFactory.getLogger(SysLogHandlerImpl.class);
	
	private static final String LOG_ACCESS = "[类名]:%s, [方法]:%s, [参数]:%s, [IP]:%s";
	private static final String LOG_ERROR = "[类名]:%s, [方法]:%s, [参数]:%s, [IP]:%s, [异常]:%s";
	
	@Autowired
	private QueueSender queueSender ;
	
	@Autowired
	private SysLogMapper mapper ;
	
	@Override
	public void saveAccessLog(ProceedingJoinPoint joinPoint) {
		HttpServletRequest request = SpringContextHolder.getRequest();
		
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Log log = (Log) signature.getMethod().getAnnotation(Log.class);
		String className = joinPoint.getTarget().getClass().getName();
		String methodName = signature.getName();
		Object[] params = joinPoint.getArgs();
		String uri = WebUtil.getCurrentURL(request, true) ;
		String paramsStr = appendParams(params, request) ;
		String ip = "非WEB访问";
		if (null != request) {
			ip = IpHelper.getIpAddr(request);
		}
		String detail = String.format(LOG_ACCESS, className, methodName, paramsStr, ip);
		Long consumeTime = System.currentTimeMillis() - SysLogAspect.getStartTimeThreadLocal(); 
		
		SysLog entity = new SysLog() ;
		entity.setType(AppConst.LOG_ACCESS_TYPE);
		entity.setConsumeTime(consumeTime.intValue());
		entity.setDescription(log.value());
		entity.setClassName(className);
		entity.setMethodName(methodName);
		entity.setUri(uri);
		entity.setParams(paramsStr);
		entity.setIp(ip);
		entity.setDetail(detail);
		entity.setUserId(null);
		entity.setUserName(null);
		
		this.save(entity);
		
		logger.debug("日志类型：{}  耗时:{}  URI:{}  最大内存:{}m  已分配内存: {}m  已分配内存中的剩余空间: {}m  最大可用内存: {}m", AppConst.LOG_ACCESS_TYPE, DateUtils.formatDateTime(consumeTime), uri, Runtime.getRuntime().maxMemory() / 1024 / 1024, Runtime.getRuntime().totalMemory() / 1024 / 1024, Runtime.getRuntime().freeMemory() / 1024 / 1024, (Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory() + Runtime.getRuntime().freeMemory()) / 1024 / 1024);

	}
	
	@Override
	public void saveErrorLog(JoinPoint joinPoint, Throwable ex) {
		HttpServletRequest request = SpringContextHolder.getRequest();
		
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Log log = (Log) signature.getMethod().getAnnotation(Log.class);
		String className = joinPoint.getTarget().getClass().getName();
		String methodName = signature.getName();
		Object[] params = joinPoint.getArgs();
		String uri = WebUtil.getCurrentURL(request, true) ;
		String paramsStr = appendParams(params, request) ;
		String ip = "非WEB访问";
		if (null != request) {
			ip = IpHelper.getIpAddr(request);
		}
		String detail = String.format(LOG_ERROR, className, methodName, paramsStr, ip, ex.getMessage());
		
		Long consumeTime = System.currentTimeMillis() - SysLogAspect.getStartTimeThreadLocal(); 
		
		SysLog entity = new SysLog() ;
		entity.setType(AppConst.LOG_ERROR_TYPE);
		entity.setConsumeTime(consumeTime.intValue());
		entity.setDescription(log.value());
		entity.setClassName(className);
		entity.setMethodName(methodName);
		entity.setUri(uri);
		entity.setParams(paramsStr);
		entity.setException(AppException.getStackTrace(ex));
		entity.setIp(ip);
		entity.setDetail(detail);
		entity.setUserId(null);
		entity.setUserName(null);
		
		this.save(entity);
		
		logger.debug("日志类型：{}  耗时:{}  URI:{}  最大内存:{}m  已分配内存: {}m  已分配内存中的剩余空间: {}m  最大可用内存: {}m", AppConst.LOG_ERROR_TYPE, DateUtils.formatDateTime(consumeTime), uri, Runtime.getRuntime().maxMemory() / 1024 / 1024, Runtime.getRuntime().totalMemory() / 1024 / 1024, Runtime.getRuntime().freeMemory() / 1024 / 1024, (Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory() + Runtime.getRuntime().freeMemory()) / 1024 / 1024);

	}
	
	/**
	 * 发送异步消息队列
	 * @param entity
	 */
	public void save(SysLog entity) {
		try {
			this.queueSender.sendObject(MQConst.SYS_LOG_QUEUE, entity);
		} catch (Exception e) {
			logger.error("JMS消息异常：" + e);
			this.mapper.insertSelective(entity) ;
		}
	}
	
	private String appendParams(Object[] params, HttpServletRequest request) {
		StringBuffer strBuf = new StringBuffer();

		if (null != request) {
			if (params != null && params.length > 0) {
				Enumeration<String> paraNames = request.getParameterNames();

				while (paraNames.hasMoreElements()) {
					String key = paraNames.nextElement();
					strBuf.append(key).append("=");
					strBuf.append(request.getParameter(key)).append("&");
				}
				if (strBuf.length() > 0 && StringUtils.isBlank(strBuf.toString())) {
					strBuf.append(request.getQueryString());
				}
			}
		}

		if (strBuf.lastIndexOf("&") != -1) {
			strBuf.deleteCharAt(strBuf.length() - 1);
		}
		if (StringUtils.isBlank(strBuf)) {
			strBuf.append("无");
		}

		return strBuf.toString();
	}

}
